<?php
/**
 * Created by PhpStorm.
 * User: 65736
 * Date: 2019/3/7 0007
 * Time: 17:57
 */

namespace app\common\widget;
use app\common\library\CommonFun;

/**
 * Class WidgetDataListTable
 * @package app\common\widget
 *
 * @method WidgetDataListTable setWidthColXs($value) 设置Xs(min-width:0px)宽度值,$value=1到12
 * @method WidgetDataListTable setWidthColSm($value) 设置Sm(min-width:768px)宽度值,$value=1到12
 * @method WidgetDataListTable setWidthColMd($value) 设置Md(min-width:992px)宽度值,$value=1到12
 * @method WidgetDataListTable setWidthColLg($value) 设置Lg(min-width:1200px)宽度值,$value=1到12
 *
 * @method WidgetButton addColButton($column, $sort = 0) 添加列按钮, $column列的field字段名, $sort按钮排序默认0
 * @method WidgetToolTip addColToolTip($column, $sort = 0) 添加ToolTip, $column列的field字段名, $sort按钮排序默认0
 *
 *
 */
class WidgetDataListTable extends WidgetCommon
{
    /**
     * 列值列表数据
     * @var array
     */
    private $columnFieldTitle =[];

    /**
     * 列表数据
     * @var array
     */
    private $dataList = [];

    /**
     * 列按钮列表
     * @var array
     */
    private $columnButtonList = [];

    /**
     * 列ToolTip列表
     * @var array
     */
    private $columnToolTipList = [];

    /**
     * 列字段显示依赖列表, keyValue数组, key为field对应的值, value为显示值
     * @var array
     */
    private $columnFieldDependence = [];

    /**
     * 最终列表数据
     * @var array
     */
    private $gridList = [];

    /**
     * Table Thead
     * @var array
     */
    private $thead = [];

    /**
     * 额外添加列
     * @var array
     */
    private $extraFieldList = [];

    /**
     * 分页代码
     * @var string
     */
    private $page_list = '';

    /**
     * 宽度列表
     * @var array
     */
    private $widthList = [
        'xs'=>WidgetConst::colxs12,
        'sm'=>WidgetConst::colsm12,
        'md'=>WidgetConst::colmd12,
        'lg'=>WidgetConst::collg12,
    ];

    /**
     * 构造方法, 渲染挂件
     * @return mixed
     * @throws \think\Exception
     */
    function render()
    {
        // 创建数据列表
        $this->createGridList();
        // 分配数据
        self::$view->assign( 'thead', $this->thead );
        self::$view->assign( 'gridList', $this->gridList );
        self::$view->assign('widthList', implode(" ", $this->widthList));
        self::$view->assign('page', $this->getPageList());
        return $this->fetch();
    }

    /**
     * @param string $page_list
     * @return WidgetDataListTable
     */
    public function setPageList(string $page_list): WidgetDataListTable
    {
        $this->page_list = $page_list;
        return $this;
    }

    /**
     * @return string
     */
    public function getPageList(): string
    {
        return $this->page_list;
    }

    /**
     * 初始化
     * @throws \think\Exception
     */
    protected function initialize()
    {
        parent::initialize();
        // 设置默认属性
        $this->setClass( ['table', 'table-striped', 'table-bordered', 'table-sm'] );
        $this->setDomAttr('cellspacing', '0');
        // 设置默认宽度
        foreach ( $this->widthList as $media=>$v ) {
            $this->setWidth( $media, $v );
        }
    }

    /**
     * __call 魔术方法
     * @param $name
     * @param $arguments
     * @return WidgetButton|WidgetToolTip|$this
     * @throws \think\Exception
     */
    public function __call($name, $arguments)
    {
        // 添加按钮
        if ( $name == "addColButton" ) {
            $buttonObj = new WidgetButton();
            $columnField = $arguments[0];
            $sort = isset($arguments[1]) ? $arguments[1] : 0;
            $this->setColumnButton($columnField, $buttonObj, $sort);
            return $buttonObj;
        }
        // 添加ToolTip
        if ( $name == "addColToolTip" ) {
            $tipObj = new WidgetToolTip();
            $columnField = $arguments[0];
            $sort = isset($arguments[1]) ? $arguments[1] : 0;
            $this->setColumnToolTip($columnField, $tipObj, $sort);
            return $tipObj;
        }
        // 匹配宽度
        if ( strpos( $name, 'setWidthCol' ) !==false ) {
            $style = str_replace( "setWidth", "", $name );
            if ( $arguments[0]<1 || $arguments[0]>12 ) $this->throwException( "数据列表宽度阈值错误" );
            $const = strtolower($style).$arguments[0];
            $width = WidgetConst::getConstant($const);
            // 匹配出media
            $pattern = "/^col([A-Za-z]*)[1-9]*/";
            preg_match($pattern,$const,$match);
            $media = $match[1];
            return $this->setWidth( $media, $width );
        }
        return $this;
    }

    /**
     * 创建数据列表
     * @return $this
     * @throws \think\Exception
     */
    private function createGridList()
    {
        foreach ( $this->columnFieldTitle as $field=>$title ) {
            $colObj = new WidgetTableColumn();
            $colObj->setColField($field);
            $colObj->setColTitle($title);
            $this->thead[] = $colObj->render();
        }

        if ( !$this->dataList ) {
            return $this;
        }

        // 过滤数据列表并格式化
        foreach ( $this->dataList as $row ) {
            // 额外列处理
            foreach ( $this->extraFieldList as $efield) {
                if ( !isset( $row[$efield] ) ) $row[$efield] = '';
            }

            // 新的行数据
            $rowData = [];
            // 检测是否有ID
            $rowID = (isset($row['id']) && $row['id'] ) ? $row['id'] :null;
            // 行属性
            $rowAttr = [];
            foreach ( $row as $_field => $item ) {
                if ( $item==='' ) continue;
                $rowAttr["attr_".$_field] = $item;
            }

            foreach ( $row as $_field => $item ) {
                // 是否在fieldTitle里面
                if ( !isset( $this->columnFieldTitle[$_field] ) ) continue;
                // 初始化
                $rowData[$_field] = '';

                // 是否设置显示依赖
                $dependence = $this->getColumnFieldDependence( $_field );
                if ( $dependence ) {
                    $rowData[$_field] = $dependence[$item];
                    continue;
                }
                // 是否设置ToolTip
                $toolTipList = $this->getColumnToolTipList( $_field );
                if ( $toolTipList ) {
                    foreach ( $toolTipList as $k=>$toolTip ) {
                        if ( $toolTip instanceof WidgetToolTip) {
                            // 设置默认class
                            $toolTip->setClass("rowToolTip_{$_field}_{$k}");
                            // 设置row原始数据
                            $toolTip->setDomAttrList($rowAttr);
                            // 设置id
                            !is_null($rowID) && $toolTip->setId("rowToolTip_{$_field}_{$k}_{$rowID}");
                            // 判断是否有Action
                            $is_action = $toolTip->getAction();
                            if ( $is_action ) {
                                $toolTip->setActionParam(['id'=>$rowID]);
                            }
                            // 渲染数据
                            $rowData[$_field] .= $toolTip->render();
                        }
                    }
                    continue;
                }

                // 是否设置button
                $buttonList = $this->getColumnButtonList( $_field );
                if ( $buttonList ) {
                    foreach ( $buttonList as $k=>$button ) {
                        if ( $button instanceof WidgetButton) {
                            // 设置默认class
                            $button->setClass( "rowButton_{$_field}_{$k}" );
                            // 设置row原始数据
                            $button->setDomAttrList( $rowAttr );
                            // 设置id
                            !is_null($rowID) && $button->setId("rowButton_{$_field}_{$k}_{$rowID}");
                            // 判断是否有Action
                            $is_action = $button->getAction();
                            if ( $is_action ) {
                                $button->setActionParam(['id'=>$rowID]);
                            }
                            // 渲染数据
                            $rowData[$_field] .= $button->render();
                        }
                    }
                    continue;
                }

                // 默认为原始数据值
                $rowData[$_field] = $item;
            }
            $this->gridList[] = array_replace($this->columnFieldTitle, $rowData);
        }
        return $this;
    }

    /**
     * 设置列字段显示依赖列表
     * @param $columnField
     * @param array $dependenceKeyValueList
     * @return $this
     * @throws \think\Exception
     */
    public function setColumnFieldDependence( $columnField, array $dependenceKeyValueList ) {
        if ( !$dependenceKeyValueList ) $this->throwException( "列字段显示依赖列表为空" );
        $this->columnFieldDependence[$columnField] = $dependenceKeyValueList;
        return $this;
    }

    /**
     * 返回列字段显示依赖列表
     * @param string $columnField
     * @return array|mixed
     */
    public function getColumnFieldDependence ( $columnField = '' ) {
        if ( $columnField ) {
            return $this->columnFieldDependence[$columnField]??[];
        }else {
            return $this->columnFieldDependence;
        }
    }

    /**
     * @param $columnField
     * @param WidgetToolTip $toolTip
     * @param int $sort
     * @return $this
     */
    private function setColumnToolTip( $columnField, WidgetToolTip &$toolTip, $sort = 0 ) {
        if ( $sort ) {
            $this->columnToolTipList[$columnField][(int)$sort] = $toolTip;
        } else {
            $this->columnToolTipList[$columnField][] = $toolTip;
        }
        return $this;
    }

    /**
     * @param $columnField
     * @param WidgetButton $button
     * @param int $sort
     * @return $this
     */
    private function setColumnButton( $columnField, WidgetButton &$button, $sort = 0 ) {
        if ( $sort ) {
            $this->columnButtonList[$columnField][(int)$sort] = $button;
        } else {
            $this->columnButtonList[$columnField][] = $button;
        }
        return $this;
    }

    /**
     * 获取按钮列表
     * @param string $columnField
     * @return array
     */
    public function getColumnButtonList( $columnField='' ): array
    {
        if ( $columnField ) {
            $buttonList = isset($this->columnButtonList[$columnField]) ? $this->columnButtonList[$columnField] : [] ;
            if ( $buttonList && CommonFun::array_is_assoc( $buttonList ) === false ) {
                ksort($buttonList);
            }
            return $buttonList;
        }else {
            return $this->columnButtonList;
        }
    }

    /**
     * 获取ToolTip列表
     * @param string $columnField
     * @return array
     */
    public function getColumnToolTipList( $columnField='' ): array
    {
        if ( $columnField ) {
            $toolTipList = isset($this->columnToolTipList[$columnField]) ? $this->columnToolTipList[$columnField] : [] ;
            if ( $toolTipList && CommonFun::array_is_assoc( $toolTipList ) === false ) {
                ksort($toolTipList);
            }
            return $toolTipList;
        }else {
            return $this->columnToolTipList;
        }
    }

    /**
     * 设置数据列表列字段和列标题
     * @param array $columnFieldTitle [filed=>title]
     * @return $this
     * @throws \think\Exception
     */
    public function setColumnFieldTitle(array $columnFieldTitle)
    {
        if ( !$columnFieldTitle ) $this->throwException( "数据列表列子段为空" );
        $this->columnFieldTitle = $columnFieldTitle;
        return $this;
    }


    /**
     * 添加一列
     * @param string $field 唯一字段名
     * @param string $title 标题
     * @return $this
     */
    public function addColumn( $field, $title ) {
        $field = trim($field);
        $title = trim($title);
        $this->columnFieldTitle[$field] = $title;
        $this->extraFieldList[] = $field;
        return $this;
    }

    /**
     * 设置数据列表数据
     * @param array $data_list
     * @return $this
     */
    public function setDataList( array $data_list ) {
        $this->dataList = $data_list;
        return $this;
    }


    /**
     * 设置宽度
     * @param $media
     * @param $width
     * @return $this
     */
    private function setWidth( $media, $width ) : WidgetDataListTable {
        $this->widthList[$media] = $width;
        return $this;
    }

    /**
     * @return array
     */
    public function getDataList(): array
    {
        return $this->dataList;
    }

    /**
     * @return array
     */
    public function getColumnFieldTitle(): array
    {
        return $this->columnFieldTitle;
    }

    /**
     * @return array
     */
    public function getWidthList(): array
    {
        return $this->widthList;
    }



}